package com.om.common;

import java.io.IOException;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.om.base.AbstractBean;
import com.om.base.AuthorizationCache;
import com.om.base.BaseConnectionManage;
import com.om.base.BeanFactory;
import com.om.base.DBConnectionManager;

import com.om.common.Authorization;

public class AuthorizationFilter implements Filter {

	protected ArrayList<String> excludeList = new ArrayList<String>();
	protected String loginUrl = "";
	protected HashMap<String, String> authorzHashMap = new HashMap<String, String>();
	protected String noticeText = "";
	protected String redirectJavascript = "";
	protected String userNameKey = "";
	protected String actionPattern = "";
	protected String displayParttern = "";
	
	
	protected String authorizationCacheClassName = null;
	protected String authorizationUserClassName = null;
	protected String beanFactoryClassName = null;
	protected String connectionManageClassName = null;
	protected String authorizationClassName = null;

	protected Class authorizationCacheClass = null;
	protected Class authorizationUserClass = null;
	protected Class beanFactoryClass = null;
	protected Class connectionManageClass = null;
	protected Class authorizationClass = null;

	// @Override
	public void destroy() {
		excludeList.clear();
	}

	// @Override
	public void doFilter(ServletRequest req, ServletResponse res,
			FilterChain chain) throws IOException, ServletException {
		String permission = "";
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		AuthorizationCache cache = AuthorizationCache.getInstance();
		BaseAuthorizationUser user =cache.getLoginUser(
				this.authorizationUserClass, request,response);
		
		String url = request.getServletPath();
		if (url.startsWith("/")) {
			url = url.substring(1);
		}
		String queryParam = request.getQueryString();

		if (queryParam != null && !"".equals(queryParam)) {
			url += "?" + queryParam;
		}

		Pattern p = Pattern.compile(actionPattern);
		Matcher m = p.matcher(url);
		if (m.find()) {
			permission = m.group(0);
		} else {
			permission = url;
		}
		boolean withAuthorization = false;
		for( int i =0;i<excludeList.size();i++){
			Pattern partten = Pattern.compile( excludeList.get(i));
			Matcher match = partten.matcher(url);
			if (match.find()) {
				withAuthorization =  true;
			}
		}
		
		//if (!excludeList.contains(url)) {
		if(!withAuthorization){

			String loginUserId = cache.getLoginUserID(request)+"" ;
			if (loginUserId == null || "".equals(loginUserId) || "null".equals(loginUserId) ) {
				response.sendRedirect(this.loginUrl);
				return;
			}
			
			ArrayList<String> userPermissionList =user.getPowerList();
			
			if (this.authorzHashMap.containsKey(permission)) {
				String permissionCode = this.authorzHashMap.get(permission)
						.toString();
				if (!userPermissionList.contains(permissionCode)) {
					response.setContentType("text/html;charset=UTF-8");
					String script = "<script>"+redirectJavascript+"</script>";

					response.getWriter().write(script);

					return;
				}
			}
		}
		
		if (req != null && user != null && this.displayParttern != null) {
			String strDisplayValue = displayParttern;
			for (int i = 0; i < user.Field.length; i++) {
				String field = "{" + user.Field[i] + "}";
				if (displayParttern.indexOf(field) != -1) {
					strDisplayValue = strDisplayValue.replace(field,
							user.getStringValue(user.Field[i]));
				}
			}
			req.setAttribute(this.userNameKey,strDisplayValue);
		}
		
		chain.doFilter(req, res);
		
		
		

		// TODO Auto-generated method stub

	}

	// @Override
	public void init(FilterConfig fc) throws ServletException {
		Connection con = null;
		try {

			this.loginUrl = fc.getInitParameter("loginUrl");
			this.noticeText = fc.getInitParameter("noticeText");
			this.userNameKey = fc.getInitParameter("userNameKey");
			this.actionPattern = fc.getInitParameter("actionPattern");
			this.redirectJavascript = fc.getInitParameter("redirectJavascript");
			this.displayParttern = fc.getInitParameter("user_dispaly_pattern");
			
			this.authorizationCacheClassName = fc
					.getInitParameter("authorizationCacheClass");
			this.beanFactoryClassName = fc.getInitParameter("beanFactoryClass");
			this.authorizationUserClassName = fc
					.getInitParameter("authorizationUserClass");
			this.connectionManageClassName = fc
					.getInitParameter("connectionManageClass");
			this.authorizationClassName = fc
					.getInitParameter("authorizationClass");

			if (authorizationCacheClassName != null
					&& !"".equals(authorizationCacheClassName)) {
				this.authorizationCacheClass = Class
						.forName(authorizationCacheClassName).newInstance()
						.getClass();
			}

			if (beanFactoryClassName != null
					&& !"".equals(beanFactoryClassName)) {
				this.beanFactoryClass = Class.forName(beanFactoryClassName)
						.newInstance().getClass();
			}

			if (authorizationUserClassName != null
					&& !"".equals(authorizationUserClassName)) {
				this.authorizationUserClass = Class
						.forName(authorizationUserClassName).newInstance()
						.getClass();
			}

			if (connectionManageClassName != null
					&& !"".equals(connectionManageClassName)) {
				this.connectionManageClass = Class
						.forName(connectionManageClassName).newInstance()
						.getClass();
			}

			if (BaseConnectionManage.ConnectionManageClass == null
					&& connectionManageClass != null) {
				BaseConnectionManage.ConnectionManageClass = connectionManageClass;
			}

			if (AuthorizationCache.AuthorizationCacheClass == null
					&& authorizationCacheClass != null) {
				AuthorizationCache.AuthorizationCacheClass = this.authorizationCacheClass;
			}

			if (BeanFactory.BeanFactoryClass == null
					&& beanFactoryClass != null) {
				BeanFactory.BeanFactoryClass = beanFactoryClass;
			}
			authorizationClass = Class.forName(authorizationClassName)
					.newInstance().getClass();

			con = BaseConnectionManage.getAvailableConnection();

			Authorization authorization = (Authorization) Class.forName(
					authorizationClass.getName()).newInstance();
			authorization.connection = con;
			ArrayList<AbstractBean> permissionList = authorization.getPermissionList();

			for (int i = 0; i < permissionList.size(); i++) {
				Authorization bean = (Authorization) permissionList.get(i);
				if (!"".equals(bean.getAuthorizationUrl())) {
					authorzHashMap.put(bean.getAuthorizationUrl(),
							bean.getAuthorizationKey());
				}
			}

			String excludes = fc.getInitParameter("excludeList").replace(
					"\\r\\n", "");

			String[] arr = excludes.split("\\,");
			for (int i = 0; i < arr.length; i++) {
				this.excludeList.add(arr[i].trim());
			}
			this.loginUrl = fc.getInitParameter("loginUrl");
			
			BaseConnectionManage.FreeConnection(con);
			
			
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

}
